#ifndef MESHFORMAT_H
#define MESHFORMAT_H
#pragma pack(push,1)

#include <d3d9.h>

#define	IBUFFER			IDirect3DIndexBuffer9
#define	VBUFFER			IDirect3DVertexBuffer9
#define	VFORMAT			IDirect3DVertexDeclaration9

#define	MAX_VBUFFERS	(4)

class ITexture;
class IVertexShader;

//--------------------------------------------------------------
//	a material
//--------------------------------------------------------------
__declspec(align(4)) struct SMatlBlend
{
	D3DBLEND	src : 8;
	D3DBLEND	dst : 8;
	D3DBLENDOP	op  : 8;
	bool		enable : 8;

};

struct SMatlComponent
{
	D3DTEXTUREOP	op     : 8;		// dx9 = 23 values, 5 bits needed
	u32				arg0   : 8;		// dx9 = 6 flags, 6 bits needed
	u32				arg1   : 8;		// dx9 = 6 flags, 6 bits needed
	u32				arg2   : 8;		// dx9 = 6 flags, 6 bits needed

	void	Setup(	D3DTEXTUREOP	iop     = D3DTOP_DISABLE,
					u32				iarg1   = D3DTA_CURRENT,
					u32				iarg2   = D3DTA_TEXTURE,
					u32				iarg0   = D3DTA_CURRENT )
	{
		op   = iop;
		arg0 = iarg0;
		arg1 = iarg1;
		arg2 = iarg2;
	}

};

struct SMatlStage
{
	SMatlComponent	color;
	SMatlComponent	alpha;
	u32				result;		// dx9 = 6 flags, 6 bits needed

	u32			unused;

	void	Reset()
	{
		color.Setup();
		alpha.Setup();
		result = D3DTA_CURRENT;
	}

} ;

struct SMatlData
{
	u32			diffuseColor;

	SMatlBlend	blend;
	SMatlStage	stages[4];

	HASH		textureNames[4];
	ITexture	*pTextures[4];

} ;

//--------------------------------------------------------------
//	a bone
//--------------------------------------------------------------
struct SMeshBoneData
{
	CVector		pivot;			// bone's pivot point
	CVector		worldOffset;	// offset from parent bone, in world space
	CVector		localOffset;	// offset from parent bone, in parent space
	s16			invRotation[4];	// inverse of bone's rotation: compressed quaternion
	u32			parentBone;		// parent bone
	HASH		nameHash;		// hash of bone's name

} ;

//--------------------------------------------------------------
//	a reference point
//--------------------------------------------------------------
struct SMeshRefPntData
{
	CVector		localOffset;	// offset from parent bone, in parent space
	s16			rotOffset[4];	// rotational offset from parent bone: compressed quaternion
	u32			parentBone;		// parent bone
	HASH		nameHash;		// hash of refpoint's name

};

//--------------------------------------------------------------
//	a strip
//--------------------------------------------------------------
struct SMeshStripData
{
	u32		materialIndex;		//	index of the material to use
	u32		firstIndex;			//	first index in the strip
	u32		numIndices;			//	# of indices in the strip
	u16		firstVertex;		//	first vertex used in the strip
	u16		numVertices;		//	# of vertices used in the strip
};



//--------------------------------------------------------------
//	a mesh
//--------------------------------------------------------------
struct SMeshData
{
	char				name[64];

	u32					numMaterials;
	u32					numStrips;
	u32					numStreams;
	u32					numRefPoints;
	u32					numIndices;
	u32					numVertices;
	u32					numBones;
	u32					vertexSize[MAX_VBUFFERS];

	struct
	{
		CVector			pos[2];
		CVector			uv[4];	// for each channel, scale is [0] & [1], bias is [2] and [3]

	} scaleBias;
	
	SMeshRefPntData		*pRefPoints;				//	reference points
	SMeshBoneData		*pBones;					//	bones
	SMatlData			*pMaterials;				//	materials
	SMeshStripData		*pStrips;					//	strips
	IBUFFER				*pIndices;					//	index buffer
	D3DVERTEXELEMENT9	*vertexDecl;				//	vertex declaration
	VFORMAT				*pVFormat;					//	vertex format
	VBUFFER				*pVertices[MAX_VBUFFERS];	//	vertex buffers

	IVertexShader		*pVShader;


	NXU::NxuPhysicsCollection *pPhysicsCollection;

	u32					physicsFmt;

//	SMeshBoneData		refPoints[];
//	SMeshBoneData		bones[];
//	SMatlData			materials[];
//	SMeshStripData		strips[];
//	D3DVERTEXELEMENT9	vDecl[];


};

#pragma pack(pop)
#endif
